﻿namespace LaoLuo
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Timers;

    /// <summary>
    /// a timer with alarm
    /// </summary>
    public class TimerWithAlarm : IDisposable, ITimerWithAlarm
    {
        /// <summary>
        /// System.Timers.Timer
        /// </summary>
        private readonly Timer _mainTimer;

        /// <summary>
        /// <see cref="_mainTimer"/>'s event handler
        /// </summary>
        private readonly Action _callback;

        /// <summary>
        /// init a <see cref="TimerWithAlarm"/>
        /// </summary>
        /// <param name="callback">action to be called</param>
        /// <param name="interval">timer's interval(milliseconds)</param>
        /// <param name="autoStart">if true, timer will start automatically</param>
        public TimerWithAlarm(Action callback, double interval = 100, bool autoStart = true)
        {
            _callback = callback;
            _mainTimer = new Timer(interval);
            _mainTimer.Elapsed += TimerElapsed;
            GC.SuppressFinalize(_mainTimer);

            if (autoStart)
            {
                _mainTimer.Start();
            }
        }

         /// <summary>
        /// init a <see cref="TimerWithAlarm"/>
        /// </summary>
        /// <param name="callback">action to be called</param>
        /// <param name="interval">timer's interval</param>
        /// <param name="autoStart">if true, timer will start automatically</param>
        public TimerWithAlarm(Action callback, TimeSpan interval, bool autoStart = true)
            :this(callback, interval.TotalMilliseconds, autoStart)
        {

        }

        /// <summary>
        /// gets timer's interval(milliseconds)
        /// </summary>
        public double Interval
        {
            get
            {
                return _mainTimer.Interval;
            }
            /*set
            {
                _mainTimer.Interval = value;
            }*/
        }

        /// <summary>
        /// start the timer
        /// </summary>
        public void Start()
        {
            _mainTimer.Start();
        }

        /// <summary>
        /// stop the timer
        /// </summary>
        public void Stop()
        {
            _mainTimer.Stop();
        }

        /// <summary>
        /// add alarm to the timer
        /// </summary>
        /// <param name="alarmTime">alarm to added</param>
        public void AddAlarm(params DateTime[] alarmTime)
        {
            if (alarmTime.Length > 0)
            {
                AddAlarm(alarmTime.AsEnumerable());
            }
        }

        /// <summary>
        /// add alarm to the timer
        /// </summary>
        /// <param name="alarmTime">alarm to added</param>
        public void AddAlarm(IEnumerable<DateTime> alarmTime)
        {
            var now = DateTime.Now;

            foreach (var item in alarmTime)
            {
                if (item > now)
                {
                    TimerOneTime.WorkOnTime(_callback, item);
                }
            }
        }

        /// <summary>
        /// dispose
        /// </summary>
        public void Dispose()
        {
            _mainTimer.Close();
            GC.ReRegisterForFinalize(_mainTimer);
        }

        /// <summary>
        /// timer's Elapsed event handler
        /// </summary>
        /// <param name="sender">event sender</param>
        /// <param name="e">event args</param>
        private void TimerElapsed(object sender, ElapsedEventArgs e)
        {
            _callback();
        }
    }
}
